From ad08f1cd83c320f2b66bb4a867b4cb71aac4f4a1 Mon Sep 17 00:00:00 2001 From: "kaf24@firebug.cl.cam.ac.uk" Date: Wed, 15 Feb 2006 15:20:32 +0100 Subject: [PATCH] Clean up grant-table code and replace uses of get_user and put_user in common code. This is an attempt to narrow the uaccess API before it gets replaced. Signed-off-by: Keir Fraser --- xen/common/grant_table.c | 333 ++++++++++++------------------- xen/common/memory.c | 23 ++- xen/common/multicall.c | 4 +- xen/drivers/char/console.c | 39 +++- xen/include/public/grant_table.h | 2 +- 5 files changed, 170 insertions(+), 231 deletions(-) diff --git a/xen/common/grant_table.c b/xen/common/grant_table.c index 6a9e99ba43..26f688f9ac 100644 --- a/xen/common/grant_table.c +++ b/xen/common/grant_table.c @@ -66,17 +66,13 @@ put_maptrack_handle( * addr is _either_ a host virtual address, or the address of the pte to * update, as indicated by the GNTMAP_contains_pte flag. */ -static int +static void __gnttab_map_grant_ref( - gnttab_map_grant_ref_t *uop) + struct gnttab_map_grant_ref *op) { - domid_t dom; - grant_ref_t ref; struct domain *ld, *rd; struct vcpu *led; - u32 dev_hst_ro_flags; int handle; - u64 addr; unsigned long frame = 0; int rc = GNTST_okay; active_grant_entry_t *act; @@ -99,39 +95,28 @@ __gnttab_map_grant_ref( led = current; ld = led->domain; - /* Bitwise-OR avoids short-circuiting which screws control flow. */ - if ( unlikely(__get_user(dom, &uop->dom) | - __get_user(ref, &uop->ref) | - __get_user(addr, &uop->host_addr) | - __get_user(dev_hst_ro_flags, &uop->flags)) ) + if ( unlikely(op->ref >= NR_GRANT_ENTRIES) || + unlikely((op->flags & (GNTMAP_device_map|GNTMAP_host_map)) == 0) ) { - DPRINTK("Fault while reading gnttab_map_grant_ref_t.\n"); - return -EFAULT; /* don't set status */ - } - - if ( unlikely(ref >= NR_GRANT_ENTRIES) || - unlikely((dev_hst_ro_flags & - (GNTMAP_device_map|GNTMAP_host_map)) == 0) ) - { - DPRINTK("Bad ref (%d) or flags (%x).\n", ref, dev_hst_ro_flags); - (void)__put_user(GNTST_bad_gntref, &uop->status); - return GNTST_bad_gntref; + DPRINTK("Bad ref (%d) or flags (%x).\n", op->ref, op->flags); + op->status = GNTST_bad_gntref; + return; } - if ( acm_pre_grant_map_ref(dom) ) + if ( acm_pre_grant_map_ref(op->dom) ) { - (void)__put_user(GNTST_permission_denied, &uop->status); - return GNTST_permission_denied; + op->status = GNTST_permission_denied; + return; } - if ( unlikely((rd = find_domain_by_id(dom)) == NULL) || + if ( unlikely((rd = find_domain_by_id(op->dom)) == NULL) || unlikely(ld == rd) ) { if ( rd != NULL ) put_domain(rd); - DPRINTK("Could not find domain %d\n", dom); - (void)__put_user(GNTST_bad_domain, &uop->status); - return GNTST_bad_domain; + DPRINTK("Could not find domain %d\n", op->dom); + op->status = GNTST_bad_domain; + return; } /* Get a maptrack handle. */ @@ -145,8 +130,8 @@ __gnttab_map_grant_ref( { put_domain(rd); DPRINTK("Maptrack table is at maximum size.\n"); - (void)__put_user(GNTST_no_device_space, &uop->status); - return GNTST_no_device_space; + op->status = GNTST_no_device_space; + return; } /* Grow the maptrack table. */ @@ -155,8 +140,8 @@ __gnttab_map_grant_ref( { put_domain(rd); DPRINTK("No more map handles available.\n"); - (void)__put_user(GNTST_no_device_space, &uop->status); - return GNTST_no_device_space; + op->status = GNTST_no_device_space; + return; } memcpy(new_mt, lgt->maptrack, PAGE_SIZE << lgt->maptrack_order); @@ -172,13 +157,13 @@ __gnttab_map_grant_ref( handle = get_maptrack_handle(ld->grant_table); } - act = &rd->grant_table->active[ref]; - sha = &rd->grant_table->shared[ref]; + act = &rd->grant_table->active[op->ref]; + sha = &rd->grant_table->shared[op->ref]; spin_lock(&rd->grant_table->lock); if ( !act->pin || - (!(dev_hst_ro_flags & GNTMAP_readonly) && + (!(op->flags & GNTMAP_readonly) && !(act->pin & (GNTPIN_hstw_mask|GNTPIN_devw_mask))) ) { sflags = sha->flags; @@ -205,7 +190,7 @@ __gnttab_map_grant_ref( prev_scombo = scombo = ((u32)sdom << 16) | (u32)sflags; new_scombo = scombo | GTF_reading; - if ( !(dev_hst_ro_flags & GNTMAP_readonly) ) + if ( !(op->flags & GNTMAP_readonly) ) { new_scombo |= GTF_writing; if ( unlikely(sflags & GTF_readonly) ) @@ -244,68 +229,68 @@ __gnttab_map_grant_ref( PIN_FAIL(unlock_out, ENOSPC, "Risk of counter overflow %08x\n", act->pin); - if ( dev_hst_ro_flags & GNTMAP_device_map ) - act->pin += (dev_hst_ro_flags & GNTMAP_readonly) ? + if ( op->flags & GNTMAP_device_map ) + act->pin += (op->flags & GNTMAP_readonly) ? GNTPIN_devr_inc : GNTPIN_devw_inc; - if ( dev_hst_ro_flags & GNTMAP_host_map ) - act->pin += (dev_hst_ro_flags & GNTMAP_readonly) ? + if ( op->flags & GNTMAP_host_map ) + act->pin += (op->flags & GNTMAP_readonly) ? GNTPIN_hstr_inc : GNTPIN_hstw_inc; spin_unlock(&rd->grant_table->lock); frame = act->frame; if ( unlikely(!mfn_valid(frame)) || - unlikely(!((dev_hst_ro_flags & GNTMAP_readonly) ? + unlikely(!((op->flags & GNTMAP_readonly) ? get_page(mfn_to_page(frame), rd) : get_page_and_type(mfn_to_page(frame), rd, PGT_writable_page))) ) PIN_FAIL(undo_out, GNTST_general_error, "Could not pin the granted frame (%lx)!\n", frame); - if ( dev_hst_ro_flags & GNTMAP_host_map ) + if ( op->flags & GNTMAP_host_map ) { - rc = create_grant_host_mapping(addr, frame, dev_hst_ro_flags); + rc = create_grant_host_mapping(op->host_addr, frame, op->flags); if ( rc != GNTST_okay ) { - if ( !(dev_hst_ro_flags & GNTMAP_readonly) ) + if ( !(op->flags & GNTMAP_readonly) ) put_page_type(mfn_to_page(frame)); put_page(mfn_to_page(frame)); goto undo_out; } - if ( dev_hst_ro_flags & GNTMAP_device_map ) + if ( op->flags & GNTMAP_device_map ) { (void)get_page(mfn_to_page(frame), rd); - if ( !(dev_hst_ro_flags & GNTMAP_readonly) ) + if ( !(op->flags & GNTMAP_readonly) ) get_page_type(mfn_to_page(frame), PGT_writable_page); } } - TRACE_1D(TRC_MEM_PAGE_GRANT_MAP, dom); + TRACE_1D(TRC_MEM_PAGE_GRANT_MAP, op->dom); - ld->grant_table->maptrack[handle].domid = dom; + ld->grant_table->maptrack[handle].domid = op->dom; ld->grant_table->maptrack[handle].ref_and_flags = - (ref << MAPTRACK_REF_SHIFT) | - (dev_hst_ro_flags & MAPTRACK_GNTMAP_MASK); + (op->ref << MAPTRACK_REF_SHIFT) | + (op->flags & MAPTRACK_GNTMAP_MASK); - (void)__put_user((u64)frame << PAGE_SHIFT, &uop->dev_bus_addr); - (void)__put_user(handle, &uop->handle); - (void)__put_user(GNTST_okay, &uop->status); + op->dev_bus_addr = (u64)frame << PAGE_SHIFT; + op->handle = handle; + op->status = GNTST_okay; put_domain(rd); - return rc; + return; undo_out: spin_lock(&rd->grant_table->lock); - if ( dev_hst_ro_flags & GNTMAP_device_map ) - act->pin -= (dev_hst_ro_flags & GNTMAP_readonly) ? + if ( op->flags & GNTMAP_device_map ) + act->pin -= (op->flags & GNTMAP_readonly) ? GNTPIN_devr_inc : GNTPIN_devw_inc; - if ( dev_hst_ro_flags & GNTMAP_host_map ) - act->pin -= (dev_hst_ro_flags & GNTMAP_readonly) ? + if ( op->flags & GNTMAP_host_map ) + act->pin -= (op->flags & GNTMAP_readonly) ? GNTPIN_hstr_inc : GNTPIN_hstw_inc; - if ( !(dev_hst_ro_flags & GNTMAP_readonly) && + if ( !(op->flags & GNTMAP_readonly) && !(act->pin & (GNTPIN_hstw_mask|GNTPIN_devw_mask)) ) clear_bit(_GTF_writing, &sha->flags); @@ -314,61 +299,56 @@ __gnttab_map_grant_ref( unlock_out: spin_unlock(&rd->grant_table->lock); - (void)__put_user(rc, &uop->status); + op->status = rc; put_maptrack_handle(ld->grant_table, handle); put_domain(rd); - return rc; } static long gnttab_map_grant_ref( - gnttab_map_grant_ref_t *uop, unsigned int count) + struct gnttab_map_grant_ref *uop, unsigned int count) { int i; + struct gnttab_map_grant_ref op; for ( i = 0; i < count; i++ ) - (void)__gnttab_map_grant_ref(&uop[i]); + { + if ( unlikely(__copy_from_user(&op, &uop[i], sizeof(op))) ) + return -EFAULT; + __gnttab_map_grant_ref(&op); + if ( unlikely(__copy_to_user(&uop[i], &op, sizeof(op))) ) + return -EFAULT; + } return 0; } -static int +static void __gnttab_unmap_grant_ref( - gnttab_unmap_grant_ref_t *uop) + struct gnttab_unmap_grant_ref *op) { domid_t dom; grant_ref_t ref; - grant_handle_t handle; struct domain *ld, *rd; active_grant_entry_t *act; grant_entry_t *sha; grant_mapping_t *map; u16 flags; s16 rc = 0; - u64 addr, dev_bus_addr; unsigned long frame; ld = current->domain; - /* Bitwise-OR avoids short-circuiting which screws control flow. */ - if ( unlikely(__get_user(addr, &uop->host_addr) | - __get_user(dev_bus_addr, &uop->dev_bus_addr) | - __get_user(handle, &uop->handle)) ) - { - DPRINTK("Fault while reading gnttab_unmap_grant_ref_t.\n"); - return -EFAULT; /* don't set status */ - } - - frame = (unsigned long)(dev_bus_addr >> PAGE_SHIFT); + frame = (unsigned long)(op->dev_bus_addr >> PAGE_SHIFT); - map = &ld->grant_table->maptrack[handle]; + map = &ld->grant_table->maptrack[op->handle]; - if ( unlikely(handle >= ld->grant_table->maptrack_limit) || + if ( unlikely(op->handle >= ld->grant_table->maptrack_limit) || unlikely(!(map->ref_and_flags & MAPTRACK_GNTMAP_MASK)) ) { - DPRINTK("Bad handle (%d).\n", handle); - (void)__put_user(GNTST_bad_handle, &uop->status); - return GNTST_bad_handle; + DPRINTK("Bad handle (%d).\n", op->handle); + op->status = GNTST_bad_handle; + return; } dom = map->domid; @@ -381,8 +361,8 @@ __gnttab_unmap_grant_ref( if ( rd != NULL ) put_domain(rd); DPRINTK("Could not find domain %d\n", dom); - (void)__put_user(GNTST_bad_domain, &uop->status); - return GNTST_bad_domain; + op->status = GNTST_bad_domain; + return; } TRACE_1D(TRC_MEM_PAGE_GRANT_UNMAP, dom); @@ -418,9 +398,10 @@ __gnttab_unmap_grant_ref( } } - if ( (addr != 0) && (flags & GNTMAP_host_map) ) + if ( (op->host_addr != 0) && (flags & GNTMAP_host_map) ) { - if ( (rc = destroy_grant_host_mapping(addr, frame, flags)) < 0 ) + if ( (rc = destroy_grant_host_mapping(op->host_addr, + frame, flags)) < 0 ) goto unmap_out; ASSERT(act->pin & (GNTPIN_hstw_mask | GNTPIN_hstr_mask)); @@ -440,7 +421,7 @@ __gnttab_unmap_grant_ref( if ( (map->ref_and_flags & (GNTMAP_device_map|GNTMAP_host_map)) == 0 ) { map->ref_and_flags = 0; - put_maptrack_handle(ld->grant_table, handle); + put_maptrack_handle(ld->grant_table, op->handle); } /* If just unmapped a writable mapping, mark as dirtied */ @@ -455,34 +436,44 @@ __gnttab_unmap_grant_ref( clear_bit(_GTF_reading, &sha->flags); unmap_out: - (void)__put_user(rc, &uop->status); + op->status = rc; spin_unlock(&rd->grant_table->lock); put_domain(rd); - return rc; } static long gnttab_unmap_grant_ref( - gnttab_unmap_grant_ref_t *uop, unsigned int count) + struct gnttab_unmap_grant_ref *uop, unsigned int count) { int i; + struct gnttab_unmap_grant_ref op; for ( i = 0; i < count; i++ ) - (void)__gnttab_unmap_grant_ref(&uop[i]); + { + if ( unlikely(__copy_from_user(&op, &uop[i], sizeof(op))) ) + goto fault; + __gnttab_unmap_grant_ref(&op); + if ( unlikely(__copy_to_user(&uop[i], &op, sizeof(op))) ) + goto fault; + } flush_tlb_mask(current->domain->domain_dirty_cpumask); - return 0; + +fault: + flush_tlb_mask(current->domain->domain_dirty_cpumask); + return -EFAULT; } static long gnttab_setup_table( - gnttab_setup_table_t *uop, unsigned int count) + struct gnttab_setup_table *uop, unsigned int count) { - gnttab_setup_table_t op; - struct domain *d; - int i; - unsigned long gmfn; + struct gnttab_setup_table op; + struct domain *d; + int i; + unsigned long gmfn; + domid_t dom; if ( count != 1 ) return -EINVAL; @@ -497,122 +488,45 @@ gnttab_setup_table( { DPRINTK("Xen only supports up to %d grant-table frames per domain.\n", NR_GRANT_FRAMES); - (void)put_user(GNTST_general_error, &uop->status); - return 0; + op.status = GNTST_general_error; + goto out; } - if ( op.dom == DOMID_SELF ) + dom = op.dom; + if ( dom == DOMID_SELF ) { - op.dom = current->domain->domain_id; + dom = current->domain->domain_id; } else if ( unlikely(!IS_PRIV(current->domain)) ) { - (void)put_user(GNTST_permission_denied, &uop->status); - return 0; + op.status = GNTST_permission_denied; + goto out; } - if ( unlikely((d = find_domain_by_id(op.dom)) == NULL) ) + if ( unlikely((d = find_domain_by_id(dom)) == NULL) ) { - DPRINTK("Bad domid %d.\n", op.dom); - (void)put_user(GNTST_bad_domain, &uop->status); - return 0; + DPRINTK("Bad domid %d.\n", dom); + op.status = GNTST_bad_domain; + goto out; } if ( op.nr_frames <= NR_GRANT_FRAMES ) { ASSERT(d->grant_table != NULL); - (void)put_user(GNTST_okay, &uop->status); + op.status = GNTST_okay; for ( i = 0; i < op.nr_frames; i++ ) { gmfn = gnttab_shared_gmfn(d, d->grant_table, i); - (void)put_user(gmfn, &op.frame_list[i]); + (void)copy_to_user(&op.frame_list[i], &gmfn, sizeof(gmfn)); } } put_domain(d); - return 0; -} - -static int -gnttab_dump_table( - gnttab_dump_table_t *uop) -{ - grant_table_t *gt; - gnttab_dump_table_t op; - struct domain *d; - u32 shared_mfn; - active_grant_entry_t *act; - grant_entry_t sha_copy; - grant_mapping_t *maptrack; - int i; - - if ( !IS_PRIV(current->domain) ) - return -EPERM; - if ( unlikely(copy_from_user(&op, uop, sizeof(op)) != 0) ) - { - DPRINTK("Fault while reading gnttab_dump_table_t.\n"); + out: + if ( unlikely(copy_to_user(uop, &op, sizeof(op))) ) return -EFAULT; - } - - if ( op.dom == DOMID_SELF ) - op.dom = current->domain->domain_id; - - if ( unlikely((d = find_domain_by_id(op.dom)) == NULL) ) - { - DPRINTK("Bad domid %d.\n", op.dom); - (void)put_user(GNTST_bad_domain, &uop->status); - return 0; - } - - ASSERT(d->grant_table != NULL); - gt = d->grant_table; - (void)put_user(GNTST_okay, &uop->status); - - shared_mfn = virt_to_maddr(d->grant_table->shared); - - DPRINTK("Grant table for dom (%hu) MFN (%x)\n", - op.dom, shared_mfn); - - ASSERT(d->grant_table->active != NULL); - ASSERT(d->grant_table->shared != NULL); - ASSERT(d->grant_table->maptrack != NULL); - - for ( i = 0; i < NR_GRANT_ENTRIES; i++ ) - { - sha_copy = gt->shared[i]; - if ( sha_copy.flags ) - DPRINTK("Grant: dom (%hu) SHARED (%d) flags:(%hx) " - "dom:(%hu) frame:(%x)\n", - op.dom, i, sha_copy.flags, sha_copy.domid, sha_copy.frame); - } - - spin_lock(>->lock); - for ( i = 0; i < NR_GRANT_ENTRIES; i++ ) - { - act = >->active[i]; - if ( act->pin ) - DPRINTK("Grant: dom (%hu) ACTIVE (%d) pin:(%x) " - "dom:(%hu) frame:(%lx)\n", - op.dom, i, act->pin, act->domid, act->frame); - } - - for ( i = 0; i < gt->maptrack_limit; i++ ) - { - maptrack = >->maptrack[i]; - if ( maptrack->ref_and_flags & MAPTRACK_GNTMAP_MASK ) - DPRINTK("Grant: dom (%hu) MAP (%d) ref:(%hu) flags:(%x) " - "dom:(%hu)\n", - op.dom, i, - maptrack->ref_and_flags >> MAPTRACK_REF_SHIFT, - maptrack->ref_and_flags & MAPTRACK_GNTMAP_MASK, - maptrack->domid); - } - - spin_unlock(>->lock); - - put_domain(d); return 0; } @@ -694,14 +608,14 @@ gnttab_prepare_for_transfer( static long gnttab_transfer( - gnttab_transfer_t *uop, unsigned int count) + struct gnttab_transfer *uop, unsigned int count) { struct domain *d = current->domain; struct domain *e; struct page_info *page; int i; grant_entry_t *sha; - gnttab_transfer_t gop; + struct gnttab_transfer gop; unsigned long mfn; for ( i = 0; i < count; i++ ) @@ -710,8 +624,7 @@ gnttab_transfer( if ( unlikely(__copy_from_user(&gop, &uop[i], sizeof(gop))) ) { DPRINTK("gnttab_transfer: error reading req %d/%d\n", i, count); - (void)__put_user(GNTST_bad_page, &uop[i].status); - return -EFAULT; /* This is *very* fatal. */ + return -EFAULT; } /* Check the passed page frame for basic validity. */ @@ -719,8 +632,8 @@ gnttab_transfer( { DPRINTK("gnttab_transfer: out-of-range %lx\n", (unsigned long)gop.mfn); - (void)__put_user(GNTST_bad_page, &uop[i].status); - continue; + gop.status = GNTST_bad_page; + goto copyback; } mfn = gmfn_to_mfn(d, gop.mfn); @@ -729,24 +642,24 @@ gnttab_transfer( { DPRINTK("gnttab_transfer: xen frame %lx\n", (unsigned long)gop.mfn); - (void)__put_user(GNTST_bad_page, &uop[i].status); - continue; + gop.status = GNTST_bad_page; + goto copyback; } if ( steal_page_for_grant_transfer(d, page) < 0 ) { - (void)__put_user(GNTST_bad_page, &uop[i].status); - continue; + gop.status = GNTST_bad_page; + goto copyback; } /* Find the target domain. */ if ( unlikely((e = find_domain_by_id(gop.domid)) == NULL) ) { DPRINTK("gnttab_transfer: can't find domain %d\n", gop.domid); - (void)__put_user(GNTST_bad_domain, &uop[i].status); page->count_info &= ~(PGC_count_mask|PGC_allocated); free_domheap_page(page); - continue; + gop.status = GNTST_bad_domain; + goto copyback; } spin_lock(&e->page_alloc_lock); @@ -767,10 +680,10 @@ gnttab_transfer( e->tot_pages, e->max_pages, gop.ref, e->domain_flags); spin_unlock(&e->page_alloc_lock); put_domain(e); - (void)__put_user(GNTST_general_error, &uop[i].status); page->count_info &= ~(PGC_count_mask|PGC_allocated); free_domheap_page(page); - continue; + gop.status = GNTST_general_error; + goto copyback; } /* Okay, add the page to 'e'. */ @@ -792,7 +705,14 @@ gnttab_transfer( put_domain(e); - (void)__put_user(GNTST_okay, &uop[i].status); + gop.status = GNTST_okay; + + copyback: + if ( unlikely(__copy_from_user(&uop[i], &gop, sizeof(gop))) ) + { + DPRINTK("gnttab_transfer: error writing resp %d/%d\n", i, count); + return -EFAULT; + } } return 0; @@ -831,9 +751,6 @@ do_grant_table_op( case GNTTABOP_setup_table: rc = gnttab_setup_table((gnttab_setup_table_t *)uop, count); break; - case GNTTABOP_dump_table: - rc = gnttab_dump_table((gnttab_dump_table_t *)uop); - break; case GNTTABOP_transfer: if (unlikely(!array_access_ok( uop, count, sizeof(gnttab_transfer_t)))) diff --git a/xen/common/memory.c b/xen/common/memory.c index 6f0d6b25cd..320e8c3d6e 100644 --- a/xen/common/memory.c +++ b/xen/common/memory.c @@ -30,7 +30,7 @@ increase_reservation( int *preempted) { struct page_info *page; - unsigned long i; + unsigned long i, mfn; if ( (extent_list != NULL) && !array_access_ok(extent_list, nr_extents, sizeof(*extent_list)) ) @@ -58,9 +58,12 @@ increase_reservation( } /* Inform the domain of the new page's machine address. */ - if ( (extent_list != NULL) && - (__put_user(page_to_mfn(page), &extent_list[i]) != 0) ) - return i; + if ( extent_list != NULL ) + { + mfn = page_to_mfn(page); + if ( unlikely(__copy_to_user(&extent_list[i], &mfn, sizeof(mfn))) ) + return i; + } } return nr_extents; @@ -93,6 +96,9 @@ populate_physmap( goto out; } + if ( unlikely(__copy_from_user(&gpfn, &extent_list[i], sizeof(gpfn))) ) + goto out; + if ( unlikely((page = alloc_domheap_pages( d, extent_order, flags)) == NULL) ) { @@ -104,9 +110,6 @@ populate_physmap( mfn = page_to_mfn(page); - if ( unlikely(__get_user(gpfn, &extent_list[i]) != 0) ) - goto out; - if ( unlikely(shadow_mode_translate(d)) ) { for ( j = 0; j < (1 << extent_order); j++ ) @@ -118,7 +121,7 @@ populate_physmap( set_gpfn_from_mfn(mfn + j, gpfn + j); /* Inform the domain of the new page's machine address. */ - if ( __put_user(mfn, &extent_list[i]) != 0 ) + if ( unlikely(__copy_to_user(&extent_list[i], &mfn, sizeof(mfn))) ) goto out; } } @@ -150,7 +153,7 @@ decrease_reservation( return i; } - if ( unlikely(__get_user(gmfn, &extent_list[i]) != 0) ) + if ( unlikely(__copy_from_user(&gmfn, &extent_list[i], sizeof(gmfn))) ) return i; for ( j = 0; j < (1 << extent_order); j++ ) @@ -282,7 +285,7 @@ long do_memory_op(int cmd, void *arg) case XENMEM_current_reservation: case XENMEM_maximum_reservation: - if ( get_user(domid, (domid_t *)arg) ) + if ( copy_from_user(&domid, (domid_t *)arg, sizeof(domid)) ) return -EFAULT; if ( likely((domid = (unsigned long)arg) == DOMID_SELF) ) diff --git a/xen/common/multicall.c b/xen/common/multicall.c index dd23a4689b..d6473a8b4b 100644 --- a/xen/common/multicall.c +++ b/xen/common/multicall.c @@ -57,7 +57,9 @@ long do_multicall(struct multicall_entry *call_list, unsigned int nr_calls) } #endif - if ( unlikely(__put_user(mcs->call.result, &call_list[i].result)) ) + if ( unlikely(__copy_to_user(&call_list[i].result, + &mcs->call.result, + sizeof(mcs->call.result))) ) { DPRINTK("Error writing result back to multicall block.\n"); goto fault; diff --git a/xen/drivers/char/console.c b/xen/drivers/char/console.c index e36285b7ca..c11fbf4cf4 100644 --- a/xen/drivers/char/console.c +++ b/xen/drivers/char/console.c @@ -224,14 +224,26 @@ static void putchar_console_ring(int c) long read_console_ring(char **pstr, u32 *pcount, int clear) { char *str = *pstr; - u32 count = *pcount; - unsigned int p, q; + unsigned int idx, len, max, sofar, c; unsigned long flags; - /* Start of buffer may get overwritten during copy. So copy backwards. */ - for ( p = conringp, q = count; (p > conringc) && (q > 0); p--, q-- ) - if ( put_user(conring[CONRING_IDX_MASK(p-1)], (char *)str+q-1) ) + max = *pcount; + sofar = 0; + + c = conringc; + while ( c != conringp ) + { + idx = CONRING_IDX_MASK(c); + len = conringp - c; + if ( (idx + len) > CONRING_SIZE ) + len = CONRING_SIZE - idx; + if ( (sofar + len) > max ) + len = max - sofar; + if ( copy_to_user(str + sofar, &conring[idx], len) ) return -EFAULT; + sofar += len; + c += len; + } if ( clear ) { @@ -240,8 +252,7 @@ long read_console_ring(char **pstr, u32 *pcount, int clear) spin_unlock_irqrestore(&console_lock, flags); } - *pstr = str + q; - *pcount = count - q; + *pcount = sofar; return 0; } @@ -347,6 +358,7 @@ long guest_console_write(char *buffer, int count) long do_console_io(int cmd, int count, char *buffer) { long rc; + unsigned int idx, len; #ifndef VERBOSE /* Only domain 0 may access the emergency console. */ @@ -363,14 +375,19 @@ long do_console_io(int cmd, int count, char *buffer) rc = 0; while ( (serial_rx_cons != serial_rx_prod) && (rc < count) ) { - if ( put_user(serial_rx_ring[SERIAL_RX_MASK(serial_rx_cons)], - &buffer[rc]) ) + idx = SERIAL_RX_MASK(serial_rx_cons); + len = serial_rx_prod - serial_rx_cons; + if ( (idx + len) > SERIAL_RX_SIZE ) + len = SERIAL_RX_SIZE - idx; + if ( (rc + len) > count ) + len = count - rc; + if ( copy_to_user(&buffer[rc], &serial_rx_ring[idx], len) ) { rc = -EFAULT; break; } - rc++; - serial_rx_cons++; + rc += len; + serial_rx_cons += len; } break; default: diff --git a/xen/include/public/grant_table.h b/xen/include/public/grant_table.h index 166e4ae327..b4244235cb 100644 --- a/xen/include/public/grant_table.h +++ b/xen/include/public/grant_table.h @@ -229,7 +229,7 @@ typedef struct gnttab_dump_table { * to the calling domain *unless* the error is GNTST_bad_page. */ #define GNTTABOP_transfer 4 -typedef struct { +typedef struct gnttab_transfer { /* IN parameters. */ unsigned long mfn; domid_t domid; -- 2.30.2